﻿using System;
using System.Collections.Concurrent;
using System.Reflection;

namespace Actor.Net
{
    /// <summary>
    /// Actor方法执行特性,需要在每一个Actor方法上加上该特性。
    /// 说明：使用该特性目的是为了解决Method.Invoke方法效率低下的问题，通过动态委托代理来代替Method.Invoke方法。
    /// </summary>
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class FuncAttribute : Attribute
    {
        /// <summary>
        /// Excute类型
        /// </summary>
        private Type ExcuteType { get; }

        /// <summary>
        /// Excute执行对象
        /// </summary>
        private ConcurrentDictionary<IActor, ConcurrentDictionary<MethodInfo, IParameter>> parameters = new ConcurrentDictionary<IActor, ConcurrentDictionary<MethodInfo, IParameter>>();

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="excuteType"></param>
        public FuncAttribute(Type excuteType)
        {
            this.ExcuteType = excuteType;
        }

        /// <summary>
        /// 创建或者从执行队列中获取一个方法执行对象
        /// </summary>
        /// <returns></returns>
        public IParameter GetParameter(IActor actor, MethodInfo method)
        {
            if(!parameters.TryGetValue(actor, out ConcurrentDictionary<MethodInfo, IParameter> dictionary))
            {
                dictionary = new ConcurrentDictionary<MethodInfo, IParameter>();
                parameters.AddOrUpdate(actor, dictionary, (k, v) => dictionary);
            }

            if(!dictionary.TryGetValue(method, out IParameter parameter))
            {
                parameter = (IParameter)Activator.CreateInstance(this.ExcuteType);
                dictionary.AddOrUpdate(method, parameter, (k, v) => parameter);
            }
            return parameter;
        }

        /// <summary>
        /// 删除一个Actor parameters
        /// </summary>
        /// <param name="actor"></param>
        public void RemoveParameters(IActor actor)
        {
            parameters.TryRemove(actor, out _);
        }
    }
}